
#include "copyright.h"

#include "../userprog/syscall.h"
#include "system.h"
#include "network.h"
#include "post.h"
#include "interrupt.h"
#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <string>

void serverTest1(){
	int returnValue;
	int lock1, lock2;
	int cond1, cond2;
	stringstream ss (stringstream::in | stringstream::out);
	int maxMailSize;
	maxMailSize = 39;
    PacketHeader outPktHdr, inPktHdr;
    MailHeader outMailHdr, inMailHdr;
	char *data = "11 9999 1111 hiImAString";
    char buffer[maxMailSize];
	
		printf("serverTest is alive!\n");
	
	outPktHdr.to = 0;
	outPktHdr.from = 2;//currentThread->getMachineId();
    outMailHdr.to = 0;
    outMailHdr.from = 1;
    outMailHdr.length = strlen(data) + 1;
	printf("Sending as %i %i.\n", outPktHdr.from, outMailHdr.from);  //DEBUG

	printf("location: %i %i.\n\n", outPktHdr.from, outMailHdr.from);  //DEBUG
	
    // Send the first message
    bool success = postOffice->Send(outPktHdr, outMailHdr, data); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	
	//printf("Going to wait to receive reply1 from server.\n");
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer);  //DEBUG
	ss << buffer;
	ss >> lock1;
	printf("LOCK CREATED\n\n");
	ss.flush();
	
	//printf("Going to request another lock creation!\n");
	char *data2 = "11 8888 1111 hiImAStringToo";
    outMailHdr.length = strlen(data2) + 1;
	outPktHdr.to = 1;
	success = postOffice->Send(outPktHdr, outMailHdr, data2); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	outPktHdr.to = 0;
	
	//printf("Going to wait to receive reply2 from server.\n");
	stringstream ss2 (stringstream::in | stringstream::out);
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer);  //DEBUG
	ss2 << buffer;
	ss2 >> lock2;
	printf("LOCK CREATED\n\n");
	ss2.flush();
	
	// -------------------------- ACQUIRE LOCK TEST \/
	
	//printf("Going to try to Acquire lock1, %d \n", lock1);
	char *data3 = "";
	stringstream ss3 (stringstream::in | stringstream::out);
	ss3 << SC_AcquireLock;
	ss3 << " ";
	ss3 << lock1;
	ss3 >> data3;
    outMailHdr.length = strlen(data3) + 1;
	success = postOffice->Send(outPktHdr, outMailHdr, data3); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	
	//printf("Going to wait to receive reply3 from server.\n");
	stringstream ss4 (stringstream::in | stringstream::out);
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer);  //DEBUG
	ss4 << buffer;
	ss4 >> returnValue;
	//printf("Message return value: %u \n\n", returnValue);
	printf("LOCK %d ACQUIRED!\n\n", returnValue);
	ss4.flush();
	
	// ------------------- ACQUIRE LOCK TWICE TEST \/
	
	//printf("Going to try to Acquire lock1 again, %d \n", lock1);
	char *data5 = "";
	stringstream ss5 (stringstream::in | stringstream::out);
	ss5 << SC_AcquireLock;
	ss5 << " ";
	ss5 << lock1;
	ss5 >> data5;
    outMailHdr.length = strlen(data5) + 1;
	success = postOffice->Send(outPktHdr, outMailHdr, data5); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	
	//printf("Going to wait to receive reply3 from server.\n");
	stringstream ss6 (stringstream::in | stringstream::out);
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer);  //DEBUG
	ss6 << buffer;
	ss6 >> returnValue;
	//printf("Message return value: %u \n\n", returnValue);
	printf("LOCK STILL ACQUIRED!\n\n");
	ss6.flush();
	
	// ---------- ACQUIRE LOCK WITH OTHER THREAD TEST \/
	
	//printf("Going to try to Acquire lock1 with outside tread, %d \n", lock1);
	char *data3a = "";
	stringstream ss3a (stringstream::in | stringstream::out);
	ss3a << SC_AcquireLock;
	ss3a << " ";
	ss3a << lock1;
	ss3a >> data3a;
	outMailHdr.from = 2;
    outMailHdr.length = strlen(data3a) + 1;
	success = postOffice->Send(outPktHdr, outMailHdr, data3a); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	outMailHdr.from = 1;
	
	//printf("NOT going to wait to receive reply3a from server.\n\n");
	printf("WAITING TO ACQUIRE LOCK!\n\n");
	
	// ------------------------ RELEASE LOCK TEST \/
	
	//printf("Going to try to Release lock1, %d \n", lock1);
	char *data7 = "";
	stringstream ss7 (stringstream::in | stringstream::out);
	ss7 << SC_ReleaseLock;
	ss7 << " ";
	ss7 << lock1;
	ss7 >> data7;
	//printf("Message return value: %u \n\n", returnValue);
    outMailHdr.length = strlen(data7) + 1;
	success = postOffice->Send(outPktHdr, outMailHdr, data7); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	
	//printf("Going to wait to receive reply4 from server.\n");
	stringstream ss8 (stringstream::in | stringstream::out);
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer);  //DEBUG
	ss8 << buffer;
	ss8 >> returnValue;
	//printf("Message return value: %u \n\n", returnValue);
	if(returnValue == 0){
		printf("LOCK RELEASED SUCCESSFULLY!\n\n");
	}
	ss8.flush();
	
	//printf("Going to wait to receive reply4a from server.\n");
	stringstream ss8a (stringstream::in | stringstream::out);
	postOffice->Receive(2, &inPktHdr, &inMailHdr, buffer);  //DEBUG
	ss8a << buffer;
	ss8a >> returnValue;
	//printf("Message return value: %u \n\n", returnValue);
	if(returnValue == 0){
		printf("LOCK RELEASE -> ACQUIRE SUCCESSFUL!\n\n");
	}
	ss8a.flush();
	
	//printf("Going to try to Release lock1 again, %d \n", lock1);
	char *data7a = "";
	stringstream ss7a (stringstream::in | stringstream::out);
	ss7a << SC_ReleaseLock;
	ss7a << " ";
	ss7a << lock1;
	ss7a >> data7a;
    outMailHdr.length = strlen(data7a) + 1;
	outMailHdr.from = 2;
	success = postOffice->Send(outPktHdr, outMailHdr, data7a); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	outMailHdr.from = 1;
	
	//printf("Going to wait to receive reply4 from server.\n");
	stringstream ss8b (stringstream::in | stringstream::out);
	postOffice->Receive(2, &inPktHdr, &inMailHdr, buffer);
	ss8b << buffer;
	ss8b >> returnValue;
	//printf("Message return value: %u \n\n", returnValue);
	if(returnValue == 0){
		printf("LOCK RELEASED AGAIN SUCCESSFULLY!\n\n");
	}
	ss8b.flush();
	
	
	// ------------------------ DESTROY LOCK TEST \/
	
	//printf("Going to try to Destroy lock1, %d \n", lock1);
	char *data9 = "";
	stringstream ss9 (stringstream::in | stringstream::out);
	ss9 << SC_DestroyLock;
	ss9 << " ";
	ss9 << lock1;
	ss9 >> data9;
    outMailHdr.length = strlen(data9) + 1;
	success = postOffice->Send(outPktHdr, outMailHdr, data9); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	
	//printf("Going to wait to receive reply5 from server.\n");
	stringstream ss10 (stringstream::in | stringstream::out);
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer);  //DEBUG
	ss10 << buffer;
	ss10 >> returnValue;
	//printf("Message return value: %u \n\n", returnValue);
	if(returnValue == 0){
		printf("LOCK DESTROYED SUCCESSFULLY!\n\n");
	}
	ss10.flush();
	
	// ---------------------------- RELEASE DESTROYED LOCK TEST \/
	char *data10z = "";
	sprintf(data10z,"%i %i %i %s", SC_ReleaseLock, lock1, 0, "thisShouldFail");
    outMailHdr.length = strlen(data7) + 1;
	success = postOffice->Send(outPktHdr, outMailHdr, data10z); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	
	//printf("Going to wait to receive reply4 from server.\n");
	stringstream ss10y (stringstream::in | stringstream::out);
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer);  //DEBUG
	ss10y << buffer;
	ss10y >> returnValue;
	//printf("Message return value: %u \n\n", returnValue);
	if(returnValue == -1){
		printf("LOCK RELEASE ON DESTROYED LOCK RETURNED AN ERROR!\n\n");
	}
	ss10y.flush();
	
	
	// ---------------------------------- CREATE COND TEST \/
	
	//printf("Going to try to Create cond1 \n");
	char *data11 = "";
	stringstream ss11 (stringstream::in | stringstream::out);
	sprintf(data11, "%i %i %i %s", SC_Condition_Create, lock2, 0, "Cond1Name");
	
    outMailHdr.length = strlen(data11) + 1;
	success = postOffice->Send(outPktHdr, outMailHdr, data11); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	
	//printf("Going to wait to receive reply6 from server.\n");
	stringstream ss12 (stringstream::in | stringstream::out);
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer);
	ss12 << buffer;
	ss12 >> cond1;
	//printf("Message return value: %u \n\n", cond1);
		printf("COND CREATED SUCCESSFULLY WITH INDEX %d!\n\n", cond1);
	ss12.flush();
	
	// ----------------------------------- WAIT COND TEST \/
	
	//printf("Going to try to wait on cond1 for lock2\n");
	char *data13 = "";
	stringstream ss13 (stringstream::in | stringstream::out);
	data13 = "18 1 0 notImportant";
    outMailHdr.length = strlen(data13) + 1;
	success = postOffice->Send(outPktHdr, outMailHdr, data13); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	
	printf("COND WAIT SUCCESSFUL!\n\n");
	
	// ---------------------------------- SIGNAL COND TEST \/
	
	//printf("Going to try to signal on cond1 for lock2\n");
	char *data14 = "";
	data14 = "17 1 0 SignalingCondition";

    outMailHdr.length = strlen(data14) + 1;
		outMailHdr.from = 2;
	success = postOffice->Send(outPktHdr, outMailHdr, data14); 
		outMailHdr.from = 1;

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	
	//printf("Going to wait to receive reply14a from server.\n");
	stringstream ss14a (stringstream::in | stringstream::out);
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer);
	ss14a << buffer;
	ss14a >> returnValue;
	//printf("Message return value: %u \n\n", returnValue);
	if(returnValue != -1){
		printf("COND SIGNAL WAITING THREAD SUCCESSFUL!\n\n");
	}
	ss14a.flush();
	
	//printf("Going to wait to receive reply14b from server.\n");
	stringstream ss14b (stringstream::in | stringstream::out);
	postOffice->Receive(2, &inPktHdr, &inMailHdr, buffer); 
	ss14b << buffer;
	ss14b >> returnValue;
	//printf("Message return value: %u \n\n", returnValue);
	if(returnValue == 0){
		printf("COND SIGNAL SUCCESSFUL!\n\n");
	}
	ss14b.flush();
	
	// ------------------------------- PREP BROADCAST TEST \/
	
	char *data15 = "";
	sprintf(data15, "%i %i %i %s", SC_Condition_Wait, lock2, cond1, "whatsInAName");
    outMailHdr.length = strlen(data15) + 1;
	for(int i = 3; i <= 5; i++){
		outMailHdr.from = i;
		success = postOffice->Send(outPktHdr, outMailHdr, data15); 

		if ( !success ) {
			printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
			interrupt->Halt();
		}
		printf("COND WAIT SUCCESSFUL!\n");
	}
	outMailHdr.from = 1;
	//STARTING BROADCAST CALL
	char *data15a = "";
	sprintf(data15a, "%i %i %i %s", SC_Condition_Broadcast, lock2, cond1, "timeToWakeUp");
    outMailHdr.length = strlen(data15a) + 1;
	success = postOffice->Send(outPktHdr, outMailHdr, data15a); 
	if ( !success ) {
			printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
			interrupt->Halt();
		}
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer);
	printf("BROADCAST CALL RETURNED!\n");
	postOffice->Receive(3, &inPktHdr, &inMailHdr, buffer);
	postOffice->Receive(4, &inPktHdr, &inMailHdr, buffer);
	postOffice->Receive(5, &inPktHdr, &inMailHdr, buffer);
	printf("ALL THREADS WOKE UP FROM BROADCAST CALL!\n\n");
	
	
	// ------------------------- DESTROY CV TEST \/
	
	//printf("Going to try to Destroy lock1, %d \n", lock1);
	char *data16 = "";
	sprintf(data16, "%i %i %i %s", SC_Condition_Destroy, 0, cond1, "deathToCV1");
    outMailHdr.length = strlen(data16) + 1;
	success = postOffice->Send(outPktHdr, outMailHdr, data16); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	
	//printf("Going to wait to receive reply5 from server.\n");
	stringstream ss16a (stringstream::in | stringstream::out);
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer);  //DEBUG
	ss16a << buffer;
	ss16a >> returnValue;
	//printf("Message return value: %u \n\n", returnValue);
	if(returnValue == 0){
		printf("CONDITION DESTROYED SUCCESSFULLY!\n\n");
	}
	ss16a.flush();
	
	// ---------------------CREATE MONITOR VARIABLE
	char *data18 = "";
	sprintf(data18, "%i %i %i %s", SC_CreateMonitor, 1, 0, "MonitorVar1");
    outMailHdr.length = strlen(data18) + 1;

	int MV1, MV2;
    success = postOffice->Send(outPktHdr, outMailHdr, data18); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer); 
	ss << buffer;
	ss >> MV1;
	printf("MV CREATED WITH INDEX: %d \n\n", MV1);
	ss.flush();
	
	// ----------------------- SET MONITOR VARIABLE
	char *data18a = "";
	sprintf(data18a, "%i %i %i %i", SC_SetMonitor, MV1, 5, 0);
    outMailHdr.length = strlen(data18a) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data18a); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer); 
	ss << buffer;
	ss >> returnValue;
	if(returnValue == 0){
		printf("MV SET SUCCESSFULLY!  ");
	}
	
	printf("MV SET TO 5 \n\n");
	ss.flush();
	
	// ----------------------- GET MONITOR VARIABLE
	char *data18b = "";
	sprintf(data18b, "%i %i %i %s", SC_GetMonitor, MV1, 0, "noImporta");
    outMailHdr.length = strlen(data18b) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data18b); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	stringstream ss19 (stringstream::in | stringstream::out);
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer); 
	ss19 << buffer;
	ss19 >> returnValue;
	printf("MV GET: %i \n\n", returnValue);
	ss19.flush();
	
	// ----------------------- DESTROY MONITOR VARIABLE
	char *data18c = "";
	sprintf(data18c, "%i %i %i %s", SC_DestroyMonitor, MV1, 0, "noImporta");
    outMailHdr.length = strlen(data18c) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data18c); 

    if ( !success ) {
		printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
		interrupt->Halt();
    }
	stringstream ss20 (stringstream::in | stringstream::out);
	postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer); 
	ss20 << buffer;
	ss20 >> returnValue;
	if(returnValue == 0){
		printf("MV DESTROYED SUCCESSFULLY! \n\n");
	}
	ss20.flush();
	
	
	
	
    interrupt->Halt();
	return;
}